package com.wangzy.game;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;


import java.util.ArrayList;
import java.util.Random;

/**
 * @ProjectName: SportBS
 * @Date: 2023/1/5
 * @Desc:游戏场景基类
 */
public class BaseGameScene extends SurfaceView implements SurfaceHolder.Callback, IGameCanvas {


    public static final int fps = 40;
    protected SurfaceHolder surfaceHolder;
    protected volatile boolean alive = false, isFinish = false;
    protected Canvas canvas;
    protected Bitmap backGround;
    protected SpriteContainer spriteContainer;//精灵容器，所有精灵的总容器
    protected DirectorThread gameDirectorThread;//导演线程（游戏刷新控制器）
    protected long refreshCount = 0;//记录游戏画布的所有刷新次数
    protected long rfps = 0;
    protected Paint basePaint;

    public static Rect GLOBALRECT = null;
    public static BaseGameScene instance;
    protected OnGameCallBack onGameCallBack;
    protected boolean inited = false;
    protected int apearWidth = 0;//游戏区域宽度
    protected Paint paintArea = new Paint();

    protected ArrayList<Bitmap> imagePool = new ArrayList<>();//所有精灵的图片缓存，考虑到一张图片可能会被多个精灵共用，所有只能在整个游戏结束时，统一是否
    protected boolean drawGrid = false;//是否绘制画布的网格（测试用）
    protected long startTime;
    protected Random random = new Random();
    protected volatile float stepGain = 0.0f;//精灵移动增益

    public BaseGameScene(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public float getStepGain() {
        return stepGain;
    }

    public void setStepGain(float stepGain) {
        this.stepGain = stepGain;
    }


    protected void init() {

        this.surfaceHolder = getHolder();
        this.surfaceHolder.addCallback(this);
        this.spriteContainer = new SpriteContainer(this);
        this.gameDirectorThread = new DirectorThread(this);
        this.basePaint = new Paint();
        this.basePaint.setAntiAlias(true);
        this.basePaint.setStrokeWidth(5);
//        this.basePaint.setColor(Color.TRANSPARENT);
        this.basePaint.setTextSize(30);

        this.paintArea = new Paint();
        this.paintArea.setAntiAlias(true);
        this.paintArea.setColor(Color.CYAN);
        this.paintArea.setStrokeWidth(5);
        this.paintArea.setStyle(Paint.Style.STROKE);
        this.paintArea.setTextSize(15);


        instance = this;
//
//        if(null==asyncPlayer){
//            asyncPlayer = new AsyncPlayer("AsyncPlayer");
//        }
    }


    private void playBgMusic() {
//        if(null!=asyncPlayer){
//            Context context=AppApplication.getInstance();
//            asyncPlayer.play(context, Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.bgm_shot_bee), true, AudioManager.STREAM_MUSIC);
//        }
    }

    public void startGame() {
        if (null != this.gameDirectorThread && !this.gameDirectorThread.isAlive()) {
            this.gameDirectorThread.start();
            startTime = System.currentTimeMillis();
        }
//        playBgMusic();
    }


    void addSprit(String key, Sprite sprite) {
        this.spriteContainer.addSprit(key, sprite);
    }

    void addSpirt(Sprite sprite) {
        this.spriteContainer.addSprit(sprite);
    }


    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }

    @Override
    public int getFps() {
        return fps;
    }

    @Override
    public boolean isEnd() {
        return isFinish;
    }

    @Override
    public long getRefreshCount() {
        return refreshCount;
    }

    @Override
    public void addSprite(Sprite sprite, Point point) {
        sprite.setPoint(point);
        this.spriteContainer.addSprit(sprite);
    }

    @Override
    public void addSprite(Sprite sprite) {
        this.spriteContainer.addSprit(sprite);
    }

    @Override
    public void addSprite(Sprite sprite, Point point, String key) {
        sprite.setPoint(point);
        this.spriteContainer.addSprit(key, sprite);

    }

    @Override
    public void addSprite(Sprite sprite, String key) {
        this.spriteContainer.addSprit(key, sprite);
    }

    @Override
    public Sprite findSpriteByKey(String key) {
        return this.spriteContainer.get(key);
    }


    private Rect bgRect = null;

    private void drawContent() {
        if (null == surfaceHolder) {
            return;
        }
        canvas = surfaceHolder.lockCanvas();
        if(null==canvas){
            return;
        }
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        //========================绘制开始
        if (null == GLOBALRECT) {
            GLOBALRECT = new Rect();
            GLOBALRECT.left = 0;
            GLOBALRECT.top = 0;
            GLOBALRECT.right = canvas.getWidth();
            GLOBALRECT.bottom = canvas.getHeight();
        }

        drawBackGround(canvas);

        if (null != backGround) {
            //这种方式绘制背景耗费性能，不建议
            if (bgRect == null) {
                bgRect = new Rect();
                bgRect.left = 0;
                bgRect.top = 0;
                bgRect.right = backGround.getWidth();
                bgRect.bottom = backGround.getHeight();
            }
            canvas.drawBitmap(backGround, bgRect, GLOBALRECT, basePaint);
        }

        if (inited == false) {
            inited = true;

            if (null != onGameCallBack) {
                onGameCallBack.onReady(this);
            }
        }

        if (0 == apearWidth) {
            apearWidth = canvas.getWidth() / 2;
        }

        if (0 != apearWidth && drawGrid) {

            Rect apearRect = new Rect();

            int left = canvas.getWidth() / 2 - apearWidth / 2;
            int top = 0;

            apearRect.left = left;
            apearRect.top = 0;
            apearRect.right = apearRect.left + apearWidth;
            apearRect.bottom = canvas.getHeight();
            canvas.drawRect(apearRect, paintArea);

            canvas.drawLine(apearRect.centerX(), apearRect.top, apearRect.centerX(), apearRect.bottom, basePaint);//中线
            int segSize = 40, sigWidth = (apearRect.right - apearRect.left) / segSize;
            for (int segment = 0; segment < 40; segment++) {
                int startX = apearRect.left + segment * sigWidth;
                int startY = apearRect.top;
                int stopX = startX;
                int stopY = apearRect.bottom;
                canvas.drawLine(startX, startY, stopX, stopY, paintArea);
//                canvas.drawText(String.valueOf(segment),startX,startY+10,paintArea);
            }
        }
//        canvas.drawText("refresh:" + refreshCount, 0, 100, this.basePaint);
//        Set<Map.Entry<String, Sprite>> allSprite = spriteContainer.enumAllSprite();

        ArrayList<Sprite> allSprite = spriteContainer.allSprite();
        ;
        for (Sprite sp : allSprite) {
            sp.update(canvas, basePaint);
        }
        drawForGround(canvas);

//        if (BuildConfig.DEBUG) {
            canvas.drawText("rfps:" + rfps, getWidth() / 2, 100, basePaint);
//        }

        //========================绘制结束
        surfaceHolder.unlockCanvasAndPost(canvas);
    }

    protected void drawBackGround(Canvas canvas) {

    }

    protected void drawForGround(Canvas canvas) {

    }


    @Override
    public void refresh() {
        if (alive == false) return;
        drawContent();
        refreshCount++;
        long usedSeconds = (runningTime() / 1000);
        if (0 != usedSeconds) {
            rfps = refreshCount / usedSeconds;
        }

    }

    public void pause() {
        if (null != gameDirectorThread) {
            gameDirectorThread.pause();
        }
    }

    public void resume() {
        if (null != gameDirectorThread) {
            gameDirectorThread.unPuase();
        }

    }


    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        alive = true;
        surfaceHolder = holder;
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
        alive = false;
    }


    public void addBitmap2Pool(Bitmap bitmap) {
//        this.imagePool.add(bitmap);
    }

    public void addBitmap2Pool(Bitmap[] frames) {
//        if (null != frames) {
//            for (Bitmap temp : frames) {
//                addBitmap2Pool(temp);
//            }
//        }
    }

    public void finishGame() {
//        if (asyncPlayer != null) {
//            asyncPlayer.stop();
//            asyncPlayer = null;
//        }
        alive = false;
        isFinish = true;
        if (null != gameDirectorThread) {
            gameDirectorThread.interrupt();
        }

        if (null != spriteContainer && !spriteContainer.isEmpty()) {
            this.spriteContainer.clear();
        }

        if (!imagePool.isEmpty()) {
            for (Bitmap bitmap : imagePool) {
                if (null != bitmap && !bitmap.isRecycled()) {
                    bitmap.recycle();
                }
            }
            imagePool.clear();
        }
    }

    public int getApearWidth() {
        return apearWidth;
    }

    public void setApearWidth(int apearWidth) {
        this.apearWidth = apearWidth;
    }

    public Bitmap getBackGround() {
        return backGround;
    }

    public void setBackGround(Bitmap backGround) {
        this.backGround = backGround;
    }

    public long getStartTime() {
        return startTime;
    }

    /**
     * 获取游戏运行时间
     *
     * @return
     */
    public long runningTime() {
        return System.currentTimeMillis() - startTime;
    }

    public long getRfps() {
        return rfps;
    }

    public void onSpriteBorn(Sprite sprite) {

    }

    public void onSpriteDead(Sprite sprite) {

    }

    public void onPropGet(Sprite sprite, BaseProp baseProp) {


    }

    public SpriteContainer getSpriteContainer() {
        return spriteContainer;
    }
}